package com.accounting.client.session.login;

import com.accounting.client.remote.Services;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.LoginHandler;
import com.accounting.client.session.LoginListener;
import com.accounting.client.session.Session;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.RootPanel;

import corelib.client.Util;
import corelib.client.jsonrpc.impl.platform.ServiceError;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.WidgetUtil;

public class LoginScreen extends Composite implements LoginHandler {
	
	private final static int WIDTH = 420;
	private static LoginScreenUiBinder uiBinder = GWT.create(LoginScreenUiBinder.class);
	
	interface LoginScreenUiBinder extends UiBinder<DivElement, LoginScreen> {
	}
	
	@UiField LoginScreenResources res;
	@UiField DivElement    container;
	@UiField DivElement    headerLineBorder;
	@UiField AnchorElement logo;
	@UiField InputElement  username;
	@UiField InputElement  password;
	@UiField InputElement  rememberMe;
	@UiField InputElement  login;
	@UiField DivElement    errorLine1;
	@UiField DivElement    errorLine2;
	
	private LoginListener listener; 
	private HandlerRegistration resizeReg;

	public LoginScreen() {
		initWidget(WidgetUtil.createWidget(uiBinder.createAndBindUi(this)));
		res.css().ensureInjected();
		resize();
		Event.sinkEvents(username, Event.ONKEYUP);
        Event.setEventListener(username, new EventListener() {
            @Override
            public void onBrowserEvent(Event event) {
				loginOnEnter(event);
            }
        });
        Event.sinkEvents(password, Event.ONKEYUP);
        Event.setEventListener(password, new EventListener() {
            @Override
            public void onBrowserEvent(Event event) {
            	loginOnEnter(event);
            }
        });
		Event.sinkEvents(login, Event.ONCLICK);
        Event.setEventListener(login, new EventListener() {
            @Override
            public void onBrowserEvent(Event event) {
            	login();
            }
        });
        resizeReg = Window.addResizeHandler(new ResizeHandler() {
			@Override
			public void onResize(ResizeEvent event) {
				resize();
			}
		});
	}

	private void resize() {
		container.getStyle().setWidth(WIDTH, Unit.PX);
	}
	
	private void loginOnEnter(Event event) {
		int keyCode = event.getKeyCode();
		if (keyCode == KeyCodes.KEY_ENTER) {
			login();
		}
	}
	
	public void login(LoginListener loginListener) {
		this.listener = loginListener;
		RootPanel.get().add(this);
		username.focus();
	}
	
	public void hide() {
		resizeReg.removeHandler();
		RootPanel.get().remove(this);
	}

	private void login() {
		
		String name = Util.getString(username.getValue()).trim();
		String pass = Util.getString(password.getValue()).trim();
		
		clearStatus(errorLine1);
		clearStatus(errorLine2);

		if (Util.isNullOrEmpty(name)) {
			setStatus(errorLine1, "Username is required");
			username.focus();
			return;
		}
		
		if (Util.isNullOrEmpty(pass)) {
			setStatus(errorLine2, "Password is required");
			password.focus();
			return;
		}
		
		login(name, pass);
	}

	private void login(final String name, final String pass) {
		SimpleModal.show("Log In...");
	    Services.LognInService.LogIn(name, pass, new AsyncCallback<Session>(){
			@Override
			public void onFailure(Throwable caught) {
				SimpleModal.hide();
				ServiceError error = ErrorHandler.convertToServiceError(caught);
				setStatus(errorLine2, error.getMessage());
				password.focus();
			}
			
			@Override
			public void onSuccess(Session result) {
				SimpleModal.hide();
				if (result != null){
					listener.onSuccess(result);
				}
			}
	    });
	}
	
	private void setStatus(DivElement elem, String msg) {
		elem.setInnerText(msg);
		elem.getStyle().setDisplay(Display.BLOCK);
	}

	private void clearStatus(DivElement elem) {
		elem.setInnerText("");
		elem.getStyle().setDisplay(Display.NONE);
	}

}